Skip to content

Lapsed donor logic#80

Open
pujitakalinadhabhotla wants to merge 3 commits intomainfrom
lapsed-donor-logic
Open

Lapsed donor logic#80
pujitakalinadhabhotla wants to merge 3 commits intomainfrom
lapsed-donor-logic

Conversation

@pujitakalinadhabhotla
Copy link
Contributor

Description

Implements Lapsed Donor Logic in the backend to identify donors whose most recent successful donation occurred more than a specified number of months ago (default: 6 months), and who do not have an active recurring donation.

Changes Made

  • Backend changes
  • Test additions/changes

Repository

  • Added findLapsedDonors(numMonths: number)
  • Filters to SUCCEEDED donations only
  • Groups by email
  • Applies HAVING MAX(createdAt) cutoff logic
  • Excludes donors with recurring donations via NOT EXISTS subquery

Service

  • Added getLapsedDonors(numMonths = 6)
  • Validates numMonths is a positive number
  • Delegates to repository
  • Returns { emails: string[] }

Controller

  • Added getLapsedDonors endpoint
  • Accepts optional numMonths
  • Defaults to 6 when not provided

Testing & Verification

  • Unit tests pass
  • Manual testing completed
  • No breaking changes

Verification Steps:

donations.repository.spec.ts

  • Filters only SUCCEEDED donations
  • Applies HAVING MAX(createdAt) cutoff
  • Ensures recurring donors are excluded
  • Normalizes and deduplicates emails
  • Validates positive numMonths

donations.service.spec.ts

  • Verifies delegation to repository
  • Validates default of 6 months
  • Ensures error thrown for non-positive values

donations.controller.spec.ts

  • Verifies service called with provided value
  • Verifies default behavior when undefined

Related Issues

Closes #69

Copy link
Collaborator

@aaronashby aaronashby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Good stuff, Pujita 👍🏾

Copy link
Collaborator

@thaninbew thaninbew left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! Most looks good, I left 2 critical suggestions.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QueryBuilder is stateful, so when we are using it qb for the main query builder we shouldn't reuse it again for the subQuery builder. This is bc it will mutate the same instance from a dirty state. It works in tests but in a real DB there can be issues. Better to be safe and use a separate this.repository.createQueryBuilder() call for the subquery and another clean one for the main query.

return stats;
}

@Get('lapsed')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For lapsed donor we also need auth since this endpoint deals with sensitive donor data. Fix is to add two lines under here:

@UseGuards(AuthGuard('jwt'))
@ApiBearerAuth()

otherwise, someone can call this endpoint and get info without auth.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Lapsed Donor Logic

3 participants